// import { createApp } from 'vue'
// import './style.css'
// import App from './App.vue'
// createApp(App).mount('#app')
// 类型注解：给变量加类型
// 语法  let 变量名:类型=值
// 简单数据类型：String,Number,Null Undefined,Boolean
// ts的类型都是小写
let str: string = 'abc'
let num: number = 123
let bol: boolean = true
let un: undefined = undefined

// 数组定义
// 语法1(推荐)：  let arr:number[]=[1,2,3]  let arr:string[]=['a', 'b', 'c', 'd']
// 语法2：  let arr2:Array<number>=[]
let arr: boolean[] = [true]
arr[1] = false
let arr2: Array<string> = ['a']

// 联合类型
//  定义类型时  类型a | 类型b | 类型c  多种类型都适用
let xxx: number | string = 123
xxx = 'hello'
let arr3: (number | string | boolean)[] = ['a', false, 1]

// 类型别名
// 语法  type 类型名 = 类型值
type Arr = (number | string | boolean)[]
let arr4: Arr = ['a', false, 1]
let arr5: Arr = ['a', true, 2]

// 函数类型
// 1：常规函数  function fn(a:number,b:number):number{ return a+b}
//   const xxx=(a:number,b:number):number=>{return a+b}
function fn (a: string, b: string): string {
  return a + b
}
fn('a', 'b')

// 2:函数赋值表达式(也支持常规函数定义方式)
//   const 函数名:(a:number,b:number)=>number =(a,b)=>{return a+b}
type Fn = (x1: number, x2: number) => number
const fn2: Fn = (a, b) => {
  return a + b
}
fn2(1, 2)

const fn3 = (a: number): number => {
  return a
}

// 函数类型：无返回值
// void:无返回值 1:没有写return  2:只写了return 3: return undefined
const fn4 = (): void => {
  return
}
// 函数参数：是否必填
//  fn(a:number,b?:number)  ？代表该参数可传可不传（非必传）
// 可选参数注意点：可选参数它后面的参数一定也要是非必传
function fn5 (a?: number, b?: number, c?: number): void {
  console.log(123)
}
fn5()

// 对象类型
const obj: {
  xxx?: number
  name: string
  age: number
  arr: number[]
  fn: () => void
} = {
  name: '张三',
  age: 18,
  arr: [1, 2, 3],
  fn () {}
}
obj.xxx = 123
type ResType = {
  msg: string
  code: number
  success: boolean
  data: {
    arr?: number[]
  }
}
const resObj: ResType = {
  msg: 'string',
  code: 0,
  success: true,
  data: {}
}

// 字面量类型
// 定义  let 变量:类型值=值
// let gender: number = 0 // 0:女  1：男
let gender: 0 | 1 = 0
gender = 1
let dir: 'left' | 'right' | 'up' | 'down' = 'up' // left right up down
dir = 'left'

// 说一下常用的ts类型
// 原始类型:number,string,boolean,null ,undefined
let a1: number = 1
let a2: string = '2'
// 联合类型
let a3: number | string = 1
a3 = 'xxx'
// 数组类型
let a4: string[] = ['a', 'b']
let a5: Array<number> = [1, 2]
// 类型别名
type T6 = string[]
let a6: T6 = ['hello']
// 函数类型
// 普通函数
function a7 (a: number, b: number): number {
  return a + b
}
// 函数赋值表达式
const a8 = (a: number): number => {
  return a
}
type T9 = (a: number) => number
const a9: T9 = a => {
  return a
}
// void:代表无返回值 1：没有写return 2:只写了return 3:return undefined
function a10 (): void {}
// 可选参数
// 可选参数后面的参数一定也要是可选
function a11 (start?: number, end?: number, dis?: number): void {}
// 对象类型
const a12: {
  name?: string
  age?: number
  fn?: (a: number) => void
} = {}
// 字面量
let a13: 0 | 1 = 0

// interface:只是用于定义对象类型的
// 语法  interface 名字 {属性名:类型.....}
interface Ia12 {
  name: string
  age: number
}
let userInfo: Ia12 = {
  name: '张三',
  age: 18
}
// 定义坐标系
// 2d
interface I2d {
  x: number
  y: number
}
const p2d: I2d = { x: 0, y: 0 }
// 3d
interface I3d {
  x: number
  y: number
  z: number
}
const p3d: I3d = { x: 0, y: 0, z: 0 }
// interface具备继承特性
// 语法  interface a extends b { 其它属性 }
interface I3d2 extends I2d {
  z: number
}
const p3d2: I3d2 = { x: 1, y: 1, z: 1 }

// interface可以重复定义（重复定义它会累加）
interface Ixx {
  name: string
}
interface Ixx {
  age: number
}
let user: Ixx = {
  name: '张三',
  age: 18
}

// interface与type有什么区别
// interface特点：只是用于定义对象类型
// type:可以用于定义所有类型
// interface：它具有继承特性
// type无继承特性  &可以完成继承的处理(实现和继承一样的效果)
// interface可重复定义（类型效果会累加）
// type不可重复定义（重复定义会报错）
type T2d = {
  x: number
  y: number
}

type T3d = T2d & { z: number }
let p3dxx: T3d = {
  x: 0,
  y: 0,
  z: 0
}

// 类型推断
let x1 = 123
function fxn () {}
let x2 = [1, 2, 3]

// any类型
let x3: any = 1
x3 = []
x3 = {}
x3 = true

// 类型断言
// 语法  值 as 类型  断言它就是某个类型
const dom = document.querySelector('#img') as HTMLImageElement
dom.src = 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'

// 泛型
// 需求：参数什么类型，返回值就什么类型
// 函数泛型 function fn<T>(a:T):T{....}  fn<T的实参类型>(...)

function add<X> (a: X): X {
  return a
}
add<number>(1)

// 类型别名的泛型
// 接口返回值类型处理
// {code:状态码,message:错误信息,data:不好确定}
type TRes<T> = {
  code: number
  message: string
  data: T
}
const loginRes: TRes<number[]> = {
  code: 200,
  message: 'ok',
  data: [1, 2, 3]
}
// 接口类型的泛型
interface IRes<T> {
  code: number
  message: string
  data: T
}
const loginRes2: IRes<number[]> = {
  code: 200,
  message: 'ok',
  data: [1, 2, 3]
}

const s1: number[] = [1]

type Xxx<T> = T[]
const s2: Array<number> = [2]
const s3: Xxx<number> = [2]

export {}
